# -*- coding: utf-8 -*-#
import datetime

from flask import session, redirect, request

from config import app, db
from model import User, CarInfo, Log
from sqlalchemy import or_


# 装饰器，用于判断是否登录
def wrapper(func):
    def inner(*args, **kwargs):
        if not session.get("user_info"):
            return redirect("/error")
        ret = func(*args, **kwargs)
        return ret

    return inner


# 登录接口
@app.route("/api/login", methods=["POST"], endpoint="login")
def login():
    # 解析从Vue项目中传递过来的数据
    userid = request.json['userid']
    password = request.json['pass']
    # 检查用户是否存在
    user = User.query.filter(User.userid == userid , User.password == password).first()
    data = {"result": False, "msg": ""}
    if user is not None:
        session["user_info"] = userid
        data["result"] = True
    else:
        data["msg"] = "用户名或密码错误！"

    return data


# 获取汽车品牌列表
@app.route("/api/get_car_list", endpoint="get_car_list")
@wrapper
def get_car_list():
    # 解析从Vue项目中传递过来的数据
    keyword = request.args.get("keyword")
    keyword = keyword if keyword is not None else ""
    like = "%{}%".format(keyword)
    # 查找汽车品牌信息
    car_list = CarInfo.query.filter(or_(CarInfo.brand.like(like),
                                        CarInfo.level.like(like)
                                        )).with_entities(CarInfo.id, CarInfo.img, CarInfo.brand).all()
    data = {"car_list": []}

    # 构建可序列化的对象
    def build_view_data(item):
        tmp_dic = {"id": item.id, "img": item.img, "brand": item.brand}
        data["car_list"].append(tmp_dic)

    [build_view_data(item) for item in car_list]
    return data


# 获取汽车品牌详情
@app.route("/api/get_car_detail", endpoint="get_car_detail")
@wrapper
def get_car_detail():
    carid = request.args.get("carid")
    # 当用户点击汽车详情的时候，插入日志
    insert_log(carid)
    # 根据ID查询汽车品牌
    car_info = CarInfo.query.get(carid)
    data = {"id": car_info.id, "img": car_info.img,
            "brand": car_info.brand, "cx_price": car_info.cx_price,
            "level": car_info.level, "rating": car_info.rating,
            "cehicle_capacity": car_info.cehicle_capacity}
    return data


# 插入日志
def insert_log(carid):
    userid = session.get("user_info")
    log = Log(userid=userid, carid=carid, lookup_time=datetime.datetime.now())
    db.session.add(log)
    db.session.commit()


# 获取推荐列表
@app.route("/api/get_recommend_list", endpoint="get_recommend_list")
@wrapper
def get_recommend_list():
    userid = session.get("user_info")
    userid = int(userid) if userid is not None else 0
    # 从会话中获取用户ID，然后调用模型即时推荐
    recommend_carid_list = exec_recommend(userid)
    # 根据推荐的汽车品牌ID获取对应的列表
    car_list = CarInfo.query.filter(CarInfo.id.in_(recommend_carid_list)).all()

    data = {"car_rec_list": []}

    def build_view_data(item):
        tmp_dic = {"id": item.id, "img": item.img, "brand": item.brand}
        data["car_rec_list"].append(tmp_dic)

    [build_view_data(item) for item in car_list]
    return data


# 执行推荐
def exec_recommend(userid):
    # 从Flask全局配置系统中获取对象
    user_df = app.config["Spark"].createDataFrame([(userid,)], ["userid"])
    user_subset_recs = app.config["Model"].recommendForUserSubset(user_df, 4)
    # 由于推荐的内容较少，可以直接调用collect；
    # 否则建议将推荐结果存入数据库，然后从数据库取推荐列表
    # 实际上，推荐内容也不会过多，一般控制到10条以内
    rows = user_subset_recs.collect()
    tmp_list = []
    for index, row in enumerate(rows[0][1]):
        tmp_list.append(row[0])
    return tmp_list


# 装饰器检查到没有登录，就向客户端反馈需要登录
@app.route("/error", endpoint="error")
def error():
    return {"result": False, "msg": "请登录！"}


if __name__ == "__main__":
    app.run(port=5000)
